import {
    CRC16,
    bytesToInt,
    hexStr2Bytes,
    stringToAsciiBytes,
    MsgType,
    DeviceMessageSend,
    DeviceMessageReceive,
    CommonConfirmReplyMsgBody,
    RecipeSendMsgBody,
    RecipeStepInfo,
    RecipeStartCookingMsgBody,
    ElectronicScaleFoodPreparationMsgBody,
    FoodWeightInfo,
    SettingSeasoningRatioCalibrationMsgBody,
    SeasoningRatioCalibrationInfo,
    ManualAddSeasoningMsgBody,
    SeasoningAddInfo,
    SettingSeasoningBaseUnitMsgBody,
    SettingDeviceCountLimitMsgBody,
} from '@/utils/deviceProtocolUtil.js'

import {
    DeviceModel, 
    DeviceStatus,
} from '@/interface/device.js'

import { deviceProtocolListenerService } from './deviceProtocolListenerService'
import { DeviceProtocolBase } from './DeviceProtocolBase'

/**
 * 设备参数设置协议服务
 */
class DeviceProtocolSettingService extends DeviceProtocolBase {
    constructor() {
        super()
    }

    /**
     * 投料校准
     * @param {String} deviceSn 设备SN号
     * @param {String} targetId 料盒地址，HEX字符串
     * @param {number} ratio 实际投料比例，小数
     */
    calibrationSeasoningRatio(deviceSn, targetId, ratio) {
        g_utils.writeLog("准备发送【投料校准】命令给设备：", deviceSn)
    
        let item = new SeasoningRatioCalibrationInfo(bytesToInt(hexStr2Bytes(targetId)), ratio)
        let msgBody = new SettingSeasoningRatioCalibrationMsgBody([item])
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.SettingSeasoningRatioCalibration, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【投料校准】命令断言函数参数：", msg)
            // 设备接收后，回复校准结果 SeasoningRatioCalibrationResultMsgBody
            let b = msg.msgBody.itemList.length > 0
            if (b) {
                g_utils.writeLog("发送【投料校准】命令成功")
            } else {
                g_utils.writeLog("发送【投料校准】命令失败")
            }
            
            // TODO: 记录设备的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    /**
     * 校准清空
     * @param {String} deviceSn 设备SN号
     * @param {Array} seasoningBoxList 料盒列表
     */
    cleanSeasoningRatio(deviceSn, seasoningBoxList) {
        g_utils.writeLog("准备发送【校准清空】命令给设备：", deviceSn)
        
        // TODO：需要根据设备的真实的料盒列表信息进行封装
    
        // for test
        let item1 = new SeasoningRatioCalibrationInfo(0x0221, 0)
        let item2 = new SeasoningRatioCalibrationInfo(0x0222, 0)
        let msgBody = new SettingSeasoningRatioCalibrationMsgBody([item1, item2])
        
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.SettingSeasoningRatioClean, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【校准清空】命令断言函数参数：", msg)
            // 设备接收后，回复校准结果 SeasoningRatioCalibrationResultMsgBody
            let b = msg.msgBody.itemList.length > 0
            if (b) {
                g_utils.writeLog("发送【校准清空】命令成功")
            } else {
                g_utils.writeLog("发送【校准清空】命令失败")
            }
            
            // TODO: 记录设备的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    /**
     * 默认投料基准单位
     * @param {String} deviceSn 设备SN号
     * @param {Number} targetId 设备地址
     * @param {Number} unitNum 该调料的默认基准单位
     */
    modifySeasoningBaseUnit(deviceSn, targetId, unitNum) {
        g_utils.writeLog("准备发送【默认投料基准单位】命令给设备：", deviceSn)
        let msgBody = new SettingSeasoningBaseUnitMsgBody(targetId, unitNum)
        
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.SettingSeasoningBaseUnit, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【默认投料基准单位】命令断言函数参数：", msg)
            // 设备接收后，回复结果 SettingSeasoningBaseUnitResultMsgBody
            let b = msg.msgBody.result > 0
            if (b) {
                g_utils.writeLog("发送【默认投料基准单位】命令成功")
            } else {
                g_utils.writeLog("发送【默认投料基准单位】命令失败")
            }
            
            // TODO: 记录设备的状态信息
            g_utils.writeLog("准备更新设备状态信息：", msg.msgBody)
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    
    /**
     * 设置炒菜机每天可炒制的菜谱数量，范围0~0xFF
     * @param {String} deviceSn 设备SN号
     * @param {Number} limitCount 限制烹饪次数
     */
    modifyDeviceCountLimit(deviceSn, limitCount) {
        g_utils.writeLog("准备发送【限制使用】命令给设备：", deviceSn)
        let msgBody = new SettingDeviceCountLimitMsgBody(limitCount)
        
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.SettingDeviceCountLimit, msgBody)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【限制使用】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 正确则回复&{limit}更新后的值
            if (b) {
                g_utils.writeLog("发送【限制使用】命令成功")
            } else {
                g_utils.writeLog("发送【限制使用】命令失败")
            }
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
    
    /**
     * 恢复出厂
     * @param {String} deviceSn 设备SN号
     */
    deviceFactoryReset(deviceSn) {
        g_utils.writeLog("准备发送【恢复出厂】命令给设备：", deviceSn)
        // 封装成发送消息
        let deviceMessageSendEntity = new DeviceMessageSend(deviceSn, MsgType.SettingFactoryReset, null)
        let deviceReplyMsgPredicate = (msg) => {
            // msg 是一个 DeviceMessageReceive 数据类型
            g_utils.writeLog("【恢复出厂】命令断言函数参数：", msg)
            // 设备接收后，回复结果 CommonConfirmReplyMsgBody
            let b = msg.msgBody.result > 0
            let status = msg.msgBody.status // 回复对应状态
            if (b) {
                g_utils.writeLog("发送【恢复出厂】命令成功")
            } else {
                g_utils.writeLog("发送【恢复出厂】命令失败")
            }
            return b
        }
        return this.deviceProtocolStore.sendMessageWithReplyPredicate(deviceMessageSendEntity, deviceReplyMsgPredicate)
    }
}

export const deviceProtocolSettingService = new DeviceProtocolSettingService()